package com.mytest.provider.service.config.security.jwt;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.mytest.common.constant.SecurityConstant;
import com.mytest.common.result.ResponseUtil;
import com.mytest.provider.service.config.security.SecurityUserDetails;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 登录成功处理类
 *
 * @author cxb
 * @date 2019-07-29 14:58
 */
@Slf4j
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    /**
     * token过期时间（分钟）
     */
    @Value("${toothDefense.tokenExpireTime}")
    private Integer tokenExpireTime;

    /**
     * 用户选择保存登录状态对应token过期时间（天）
     */
    @Value("${toothDefense.saveLoginTime}")
    private Integer saveLoginTime;

    /**
     * 后台过期时间
     */
    @Value("${toothDefense.manageTokenExpireTime}")
    private Integer manageTokenExpireTime;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 将Authentication里面的用户信息封装成token,返回
     * @param request
     * @param response
     * @param authentication
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws ServletException, IOException {
        //用户选择保存登录状态几天
        String saveTime = request.getParameter(SecurityConstant.SAVE_LOGIN);
        if (StringUtils.isNotBlank(saveTime) && Boolean.valueOf(saveTime)) {
            tokenExpireTime = saveLoginTime * 60 * 24;
        }
        SecurityUserDetails userDetails = (SecurityUserDetails) authentication.getPrincipal();

        String username = request.getParameter("username");
        String IP = request.getHeader("x-forwarded-for");
        /*LogOperation logOperation = new LogOperation();
        //记录操作日志
        logOperation.setOperateType(1)
                .setOperateName("用户登录")
                .setReqMethod("loadUserByUsername")
                .setOperateUser(username)
                .setThreadName(Thread.currentThread().getName())
                .setIpAddress(IP)
                .setTimestmp(DateUtil.date());*/
//        logOperationService.insert(logOperation);

//        String username = userDetails.getUsername();
        List<GrantedAuthority> list = (List<GrantedAuthority>) userDetails.getAuthorities();
        List<String> authorities = Lists.newArrayList();
        for (GrantedAuthority grantedAuthority : list) {
            authorities.add(grantedAuthority.getAuthority());
        }
        //登录成功生成jwt
        String token = Jwts.builder().setSubject(JSONObject.toJSONString(userDetails))
                .claim(SecurityConstant.AUTHORITIES, JSONObject.toJSONString(authorities))
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000))
                .signWith(SignatureAlgorithm.HS512, SecurityConstant.JWT_SIGN_KEY)
                .compact();

        token = SecurityConstant.TOKEN_SPLIT + token;

        // todo 将token存入redis
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        Random rand = new Random();
        int random = rand.nextInt(89999)+10000;
        String userId = userDetails.getId().toString();
        String userIdStr = random+simpleDateFormat.format(new Date())+"tokManage"+userId+"en";
        redisTemplate.opsForValue().set(userIdStr, token,manageTokenExpireTime, TimeUnit.MINUTES);

        //将ip存入redis中并且给他设置时间
        String ipAddress1 = request.getHeader("X-Real-IP");
        String ipAddress2 = request.getHeader("X-Forwarded-For");
        log.info("ipAddress1:"+ipAddress1);
        log.info("ipAddress2:"+ipAddress2);

        redisTemplate.opsForValue().set(userIdStr+"Ip", ipAddress1,manageTokenExpireTime, TimeUnit.MINUTES);


        Map<String, Object> resultMap = ResponseUtil.resultMap(true, 200, "登录成功", userIdStr);
        //authentication里面获取到的用户信息
        resultMap.put("userInfo", getUserInfo(userDetails));
        // 返回用户信息
        ResponseUtil.out(response, resultMap);
    }

    private JSONObject getUserInfo(SecurityUserDetails userDetails) {
        JSONObject userInfo = new JSONObject();
        userInfo.put("userId", userDetails.getId());
        userInfo.put("userName", userDetails.getUsername());
        userInfo.put("nickName", userDetails.getNickName());
        userInfo.put("status", userDetails.getStatus());
        userInfo.put("sex", userDetails.getSex());
        return userInfo;
    }
}
